using System;
using System.Collections.Generic;
using Opc.Ua;
using Opc.Ua.Client;

namespace HslCommunicationEx.OpcUa
{
	public static class FormUtils
	{
		public static NodeId[] KnownEventTypes = new NodeId[8]
		{
			ObjectTypeIds.BaseEventType,
			ObjectTypeIds.ConditionType,
			ObjectTypeIds.DialogConditionType,
			ObjectTypeIds.AlarmConditionType,
			ObjectTypeIds.ExclusiveLimitAlarmType,
			ObjectTypeIds.NonExclusiveLimitAlarmType,
			ObjectTypeIds.AuditEventType,
			ObjectTypeIds.AuditUpdateMethodEventType
		};

		public static EndpointDescription SelectEndpoint(string discoveryUrl, bool useSecurity)
		{
			if (!discoveryUrl.StartsWith("opc.tcp") && !discoveryUrl.EndsWith("/discovery"))
			{
				discoveryUrl += "/discovery";
			}
			Uri uri = new Uri(discoveryUrl);
			EndpointConfiguration endpointConfiguration = EndpointConfiguration.Create();
			endpointConfiguration.OperationTimeout = 5000;
			EndpointDescription endpointDescription = null;
			using (DiscoveryClient discoveryClient = DiscoveryClient.Create(uri, endpointConfiguration))
			{
				EndpointDescriptionCollection endpoints = discoveryClient.GetEndpoints(null);
				for (int i = 0; i < endpoints.Count; i++)
				{
					EndpointDescription endpointDescription2 = endpoints[i];
					if (endpointDescription2.EndpointUrl.StartsWith(uri.Scheme))
					{
						if (endpointDescription == null)
						{
							endpointDescription = endpointDescription2;
						}
						if (useSecurity)
						{
							if (endpointDescription2.SecurityMode != MessageSecurityMode.None && endpointDescription2.SecurityLevel > endpointDescription.SecurityLevel)
							{
								endpointDescription = endpointDescription2;
							}
						}
						else if (endpointDescription2.SecurityMode == MessageSecurityMode.None)
						{
							endpointDescription = endpointDescription2;
						}
					}
					if (endpointDescription == null && endpoints.Count > 0)
					{
						endpointDescription = endpoints[0];
					}
				}
			}
			Uri uri2 = Utils.ParseUri(endpointDescription.EndpointUrl);
			if (uri2 != null && uri2.Scheme == uri.Scheme)
			{
				UriBuilder uriBuilder = new UriBuilder(uri2);
				uriBuilder.Host = uri.DnsSafeHost;
				uriBuilder.Port = uri.Port;
				endpointDescription.EndpointUrl = uriBuilder.ToString();
			}
			return endpointDescription;
		}

		public static NodeId FindEventType(MonitoredItem monitoredItem, EventFieldList notification)
		{
			EventFilter eventFilter = monitoredItem.Status.Filter as EventFilter;
			if (eventFilter != null)
			{
				for (int i = 0; i < eventFilter.SelectClauses.Count; i++)
				{
					SimpleAttributeOperand simpleAttributeOperand = eventFilter.SelectClauses[i];
					if (simpleAttributeOperand.BrowsePath.Count == 1 && simpleAttributeOperand.BrowsePath[0] == "EventType")
					{
						return notification.EventFields[i].Value as NodeId;
					}
				}
			}
			return null;
		}

		public static BaseEventState ConstructEvent(Session session, MonitoredItem monitoredItem, EventFieldList notification, Dictionary<NodeId, NodeId> eventTypeMappings)
		{
			NodeId nodeId = FormUtils.FindEventType(monitoredItem, notification);
			if (nodeId == null)
			{
				return null;
			}
			NodeId value = null;
			if (!eventTypeMappings.TryGetValue(nodeId, out value))
			{
				for (int i = 0; i < FormUtils.KnownEventTypes.Length; i++)
				{
					if (FormUtils.KnownEventTypes[i] == nodeId)
					{
						value = nodeId;
						eventTypeMappings.Add(nodeId, nodeId);
						break;
					}
				}
				if (value == null)
				{
					ReferenceDescriptionCollection referenceDescriptionCollection = FormUtils.BrowseSuperTypes(session, nodeId, throwOnError: false);
					if (referenceDescriptionCollection == null)
					{
						return null;
					}
					for (int j = 0; j < referenceDescriptionCollection.Count; j++)
					{
						for (int k = 0; k < FormUtils.KnownEventTypes.Length; k++)
						{
							if (FormUtils.KnownEventTypes[k] == referenceDescriptionCollection[j].NodeId)
							{
								value = FormUtils.KnownEventTypes[k];
								eventTypeMappings.Add(nodeId, value);
								break;
							}
						}
						if (value != null)
						{
							break;
						}
					}
				}
			}
			if (value == null)
			{
				return null;
			}
			uint? num = value.Identifier as uint?;
			if (!num.HasValue)
			{
				return null;
			}
			BaseEventState baseEventState = null;
			baseEventState = num.Value switch
			{
				2782u => new ConditionState(null), 
				2830u => new DialogConditionState(null), 
				2915u => new AlarmConditionState(null), 
				9341u => new ExclusiveLimitAlarmState(null), 
				9906u => new NonExclusiveLimitAlarmState(null), 
				2052u => new AuditEventState(null), 
				2127u => new AuditUpdateMethodEventState(null), 
				_ => new BaseEventState(null), 
			};
			EventFilter eventFilter = monitoredItem.Status.Filter as EventFilter;
			baseEventState.Update(session.SystemContext, eventFilter.SelectClauses, notification);
			baseEventState.Handle = notification;
			return baseEventState;
		}

		public static ReferenceDescriptionCollection Browse(Session session, BrowseDescription nodeToBrowse, bool throwOnError)
		{
			try
			{
				ReferenceDescriptionCollection referenceDescriptionCollection = new ReferenceDescriptionCollection();
				BrowseDescriptionCollection browseDescriptionCollection = new BrowseDescriptionCollection();
				browseDescriptionCollection.Add(nodeToBrowse);
				BrowseResultCollection results = null;
				DiagnosticInfoCollection diagnosticInfos = null;
				session.Browse(null, null, 0u, browseDescriptionCollection, out results, out diagnosticInfos);
				ClientBase.ValidateResponse(results, browseDescriptionCollection);
				ClientBase.ValidateDiagnosticInfos(diagnosticInfos, browseDescriptionCollection);
				while (true)
				{
					if (StatusCode.IsBad(results[0].StatusCode))
					{
						throw new ServiceResultException(results[0].StatusCode);
					}
					for (int i = 0; i < results[0].References.Count; i++)
					{
						referenceDescriptionCollection.Add(results[0].References[i]);
					}
					if (results[0].References.Count == 0 || results[0].ContinuationPoint == null)
					{
						break;
					}
					ByteStringCollection byteStringCollection = new ByteStringCollection();
					byteStringCollection.Add(results[0].ContinuationPoint);
					session.BrowseNext(null, releaseContinuationPoints: false, byteStringCollection, out results, out diagnosticInfos);
					ClientBase.ValidateResponse(results, byteStringCollection);
					ClientBase.ValidateDiagnosticInfos(diagnosticInfos, byteStringCollection);
					bool flag = true;
				}
				return referenceDescriptionCollection;
			}
			catch (Exception e)
			{
				if (throwOnError)
				{
					throw new ServiceResultException(e, 2147549184u);
				}
				return null;
			}
		}

		public static ReferenceDescriptionCollection BrowseSuperTypes(Session session, NodeId typeId, bool throwOnError)
		{
			ReferenceDescriptionCollection referenceDescriptionCollection = new ReferenceDescriptionCollection();
			try
			{
				BrowseDescription browseDescription = new BrowseDescription();
				browseDescription.NodeId = typeId;
				browseDescription.BrowseDirection = BrowseDirection.Inverse;
				browseDescription.ReferenceTypeId = ReferenceTypeIds.HasSubtype;
				browseDescription.IncludeSubtypes = false;
				browseDescription.NodeClassMask = 0u;
				browseDescription.ResultMask = 63u;
				ReferenceDescriptionCollection referenceDescriptionCollection2 = FormUtils.Browse(session, browseDescription, throwOnError);
				while (referenceDescriptionCollection2 != null && referenceDescriptionCollection2.Count > 0)
				{
					referenceDescriptionCollection.Add(referenceDescriptionCollection2[0]);
					if (referenceDescriptionCollection2[0].NodeId.IsAbsolute)
					{
						break;
					}
					browseDescription.NodeId = (NodeId)referenceDescriptionCollection2[0].NodeId;
					referenceDescriptionCollection2 = FormUtils.Browse(session, browseDescription, throwOnError);
				}
				return referenceDescriptionCollection;
			}
			catch (Exception e)
			{
				if (throwOnError)
				{
					throw new ServiceResultException(e, 2147549184u);
				}
				return null;
			}
		}
	}
}
